package com.example.hyg_veintype.base.api;

import android.util.Log;

import com.google.gson.Gson;
import com.hyg.lib_base.Net.SSLSocketFactoryCompat;


import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * @author: yyw
 * time: 2020/12/22 15:39
 * desc:
 */
public class ApiServiceManager {
    private static final long TIMEOUT = 30;

    private volatile static ApiServiceManager instance;

    private ApiServiceManager() {
    }

    public static ApiServiceManager getInstance() {
        if (instance == null) {
            synchronized (ApiServiceManager.class) {
                if (instance == null) {
                    instance = new ApiServiceManager();
                }
            }
        }
        return instance;
    }

    public <T> void getRequest(String url, Class<T> clazz, IGsonResponse<T> gsonResponse) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LogInterceptor())
                .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
                .sslSocketFactory(new SSLSocketFactoryCompat(setSSL(url)), setSSL(url))
                .build();

        Request request = new Request
                .Builder()
                .url(url)
                .build();

        sethttpCall(okHttpClient, request, clazz, gsonResponse);
    }

    public <T> void postRequest(String url, FormBody formBody, Class<T> clazz, IGsonResponse<T> gsonResponse) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LogInterceptor())
                .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
                .sslSocketFactory(new SSLSocketFactoryCompat(setSSL(url)), setSSL(url))
                .build();

        //Form表单格式的参数传递
        Request request = new Request
                .Builder()
                .post(formBody)
                .url(url)
                .build();
        sethttpCall(okHttpClient, request,clazz, gsonResponse);
    }

    public <T> void sethttpCall(OkHttpClient okHttpClient, Request request, Class<T> clazz, IGsonResponse<T> gsonResponse) {
        IBaseResponseHandler handler=new IBaseResponseHandler(gsonResponse);

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            gsonResponse.onError(e.getMessage() + "");
                        } catch (Exception es) {
                            es.printStackTrace();
                        }
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        T mode = null;
                        try {
                            mode = (T) new Gson().fromJson(result, clazz);
                            gsonResponse.onSuccess(mode, result);
                        } catch (Exception e) {
                            gsonResponse.onError("数据解析错误!");
                        }
                    }
                });
            }
        });
    }

    /**
     * 网络接口返回信息打印
     */
    private class LogInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());
            String result = response.body().string();
            String url = response.request().url().toString();
            String headers = response.headers().toString();
            MediaType type = response.body().contentType();

            Log.d("拦截器=", String.format("url:%s\nresult headers:%s\nresult:%s", url, headers, result));

            return response.newBuilder().body(ResponseBody.create(type, result)).build();
        }
    }

    public X509TrustManager setSSL(String url) {
        //定义一个信任所有证书的TrustManager 兼容5.0系统以下可以使用https连接
        final X509TrustManager trustAllCert = new X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            // 如果使用自定义X509TrustManager实现类，必须在checkServerTrusted() 方法中校验服务端证书的合法性，否则可能受到中间人攻击
            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                HostnameVerifier hnv = new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        if (url.equals(hostname)) {
                            return true;
                        } else {
                            HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                            return hv.verify(hostname, session);
                        }
                    }
                };
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }
        };

        return trustAllCert;
    }

}
